﻿/**
 *	(C) 2014 Yuanjj
 *
 *	define db class
 *
 *	histroy
 * 		2014-07-01	Yuanjj		-	create
 */

#include "db.h"
#include "errorcode.h"
#include "routine/global.h"
#include "routine/option/opt.h"

/********************************************************************
 *	ping_thread	
 ********************************************************************/
ping_thread::ping_thread()
{
	m_condb		= NULL;
}

ping_thread::~ping_thread()
{
}

/**
 *	set mysql object
 *
 *	@condb		[in] the mysql object pointer
 */
pem_void_t ping_thread::set_mysql_obj( MYSQL* condb )
{
	m_condb = condb;
}

/**
 *	thread fun for ping
 */
pem_void_t ping_thread::run()
{
	while( !m_stop )
	{
		mysql_ping( m_condb );
		sleep( 2 );
	}
}

/********************************************************************
 *	cls_res
 ********************************************************************/
cls_res::cls_res()
{
    m_res		= NULL;
    m_row		= NULL;
    m_fnum		= -1;
    m_rnum		= -1;
}

cls_res::~cls_res()
{
}

/**
 *	get field count
 *
 * 	return
 * 		the field count
 */
pem_u32_t cls_res::get_field_num()
{
    return m_fnum;
}

/**
 *	get next row
 *
 * 	return
 * 		==	true		get a new row
 * 		==	false		no new row for getting
 */
pem_bool_t cls_res::get_next_row()
{
    m_row = mysql_fetch_row( m_res );

    return (NULL != m_row);
}

/**
 *	get bool data
 *
 *	@index		[in] the index of column in a row
 *	@truetext	[in] the text for true
 *	@size		[in] the data buffer size
 *
 * 	return
 * 		the result
 */
pem_bool_t cls_res::get_data_bool( pem_s32_t index, pem_s8_t* truetext, pem_u32_t size )
{
    return ( 0 == strncmp( m_row[index], truetext, size ));
}

/**
 *	get string data
 *
 *	@index		[in] the index of column in a row
 *	@pdata		[out] the data buffer
 *	@size		[in] the data buffer size
 */
pem_void_t cls_res::get_data_string( pem_s32_t index, pem_s8_t* pdata, pem_u32_t size )
{
    strncpy( pdata, m_row[index], size );
}

/**
 *	get usnigned int data
 *
 *	@index		[in] the index of column in a row
 *
 *	return
 * 		the result
 */
pem_u32_t cls_res::get_data_int( pem_s32_t index )
{
    return atol( m_row[index] );
}

/**
 *	free res
 */
pem_void_t cls_res::free_res()
{
    if ( NULL == m_res )
        return;

    mysql_free_result( m_res );
    m_res	= NULL;
    m_row	= NULL;
    m_fnum	= -1;
    m_rnum	= -1;
}

/**
 *	over load operator "="
 */
cls_res& cls_res::operator=( MYSQL_RES* res )
{
    m_res	= res;
    if ( NULL == m_res )
        return *this;

    m_fnum	= mysql_num_fields( m_res );
    m_rnum	= 0;

    return *this;
}

/**
 *	over load operator "=="
 */
pem_bool_t cls_res::operator==( MYSQL_RES* res )
{
    return ( res == m_res );
}

/********************************************************************
 *	cls_db
 ********************************************************************/
cls_db::cls_db()
{
    pem_s8_t	value = 1;

    _INIT_LOCK( &m_lock );

    mysql_init( &m_condb );
    mysql_options( &m_condb, MYSQL_OPT_RECONNECT, &value );
}

cls_db::~cls_db()
{
    _DEL_LOCK( &m_lock );
}

/**
 *	initialize the data base object
 *
 * 	return
 * 		==	PEM_OK		successful
 * 		!=	PEM_OK		errorcode
 */
pem_error_t cls_db::instance()
{
    pem_error_t		res;
    opt_info		opt;

    g_opt.get_opt( opt );

    _LOCK( &m_lock );

    res = _connect_mysql( opt.db_ip, opt.db_user, opt.db_passwd, opt.db_name, opt.db_port );
    if ( PEM_OK != res )
    {
        g_log.write( LOG_ERR, "db", "create connect to db failed[error = 0x%x]", res );
        goto EXIT;
    }

    res = _set_character_set( opt.db_set );
    if ( PEM_OK != res )
    {
        g_log.write( LOG_ERR, "db", "set connect character set failed[error = 0x%x]", res );
        _close_connect();
        goto EXIT;
    }

	m_ping.set_mysql_obj( &m_condb );
	m_ping.start_thread();

    _UNLOCK( &m_lock );

EXIT:
    return res;
}

/**
 *	release the data base object
 */
pem_void_t cls_db::release()
{
    _LOCK( &m_lock );

    m_ping.stop_thread();
    _close_connect();

    _UNLOCK( &m_lock );
}

/**
 *	query sql
 *
 * 	@sql		[in] sql string
 *
 * 	return
 * 		==	PEM_OK		successful
 * 		!=	PEM_OK		errorcode
 */
pem_error_t cls_db::query( const pem_s8_t* sql )
{
    pem_error_t		res = PEM_OK;

    if ( 0 != mysql_query( &m_condb, sql ) )
    {
        res = mysql_errno( &m_condb );
        res = BUILD_ERRORCODE( res, PEM_MYSQL_QUERY );
    }

    return	res;
}

/**
 *	get error text
 *
 * 	return
 * 		the error text
 */
const pem_s8_t* cls_db::get_error()
{
    return mysql_error( &m_condb );
}

/**
 *	get query result
 *
 * 	return
 * 		==	PEM_OK		successful
 * 		!=	PEM_OK		errorcode
 */
pem_error_t cls_db::get_res( cls_res& sqlres )
{
    pem_error_t		res	= PEM_OK;

    sqlres = mysql_store_result( &m_condb );
    if ( sqlres == NULL )
    {
        res = mysql_errno( &m_condb );
        res = BUILD_ERRORCODE( res, PEM_MYSQL_RESULT );
    }

    return	res;
}

/**
 *	connect to mysql database
 *
 * 	@host			[in] the host address
 * 	@user			[in] user name
 * 	@passwd			[in] user pass word
 * 	@db				[in] data base name
 * 	@port			[in] host port
 *
 * 	return
 * 		==	PEM_OK		successful
 * 		!=	PEM_OK		errorcode
 */
pem_error_t cls_db::_connect_mysql( pem_s8_t* host, pem_s8_t* user, pem_s8_t* passwd, pem_s8_t* db, pem_u16_t port )
{
    pem_error_t		res = PEM_OK;
    pem_s32_t		err	= 0;

    if ( NULL == mysql_real_connect( &m_condb, host, user, passwd, db, port, NULL, 0 ) )
    {
        err = mysql_errno(&m_condb);
        return BUILD_ERRORCODE( err, PEM_MYSQL_CONNECT );
    }

    return	res;
}

/**
 *	set character set
 *
 * 	@name		[in] character set name ( "gbk", "utf8" and so on )
 *
 * 	return
 * 		==	PEM_OK		successful
 * 		!=	PEM_OK		errorcode
 */
pem_error_t cls_db::_set_character_set( pem_s8_t* name )
{
    pem_error_t		res = PEM_OK;

    if ( mysql_set_character_set( &m_condb, name ) )
    {
        res	= mysql_errno( &m_condb );
        res = BUILD_ERRORCODE( res, PEM_MYSQL_CHARSET );
    }

    return	res;
}

/**
 *	close connect
 */
pem_void_t cls_db::_close_connect()
{
    mysql_close( &m_condb );
}
